using System.CodeDom;
using System.Collections.Generic;
using System.ComponentModel;
using Roslyn.Compilers.CSharp;

namespace InterfaceWeaver.CustomTool
{
    public class DefaultValueAspectHandler : AspectHandlerBase<DefaultValueAttribute>
    {
        /// <summary>
        /// Regarding all the handler answering preview step, this step determines whether there are some aspect handler that should be removed from next live cycle.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="attributeSyntax">The attribute syntax.</param>
        /// <param name="indirectAspectHandler"> </param>
        /// <param name="indirectAttributeSyntax"> </param>
        /// <returns></returns>
        public override bool IsIndirectAspectsCompliantOnInterface(AspectDispatcher context, AttributeSyntax attributeSyntax, IAspectHandler indirectAspectHandler, AttributeSyntax indirectAttributeSyntax)
        {
            return !(indirectAspectHandler is MapDependencyPropertyAspectHandler || indirectAspectHandler is MapCommandAspectHandler);
        }

        /// <summary>
        /// Regarding all the handler answering preview step, this step determines whether there are some aspect handler that should be removed from next live cycle.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="attributeSyntax">The attribute syntax.</param>
        /// <param name="indirectAspectHandler"> </param>
        /// <param name="indirectAttributeSyntax"> </param>
        /// <returns></returns>
        public override bool IsIndirectAspectsCompliantOnProperty(AspectDispatcher context, AttributeSyntax attributeSyntax, IAspectHandler indirectAspectHandler, AttributeSyntax indirectAttributeSyntax)
        {
            return !(indirectAspectHandler is MapDependencyPropertyAspectHandler || indirectAspectHandler is MapCommandAspectHandler);
        }

        /// <summary>
        /// Handles the on member.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="attributeSyntax">The attribute syntax.</param>
        /// <param name="propertyDeclarationSyntax"> </param>
        /// <param name="handlerStreams"> </param>
        /// <returns>
        /// True if the aspect is handled, false otherwise
        /// </returns>
        public override void HandleOnProperty(AspectDispatcher context, AttributeSyntax attributeSyntax, PropertyDeclarationSyntax propertyDeclarationSyntax, IDictionary<PropertyDeclarationSyntax, AspectTuple[]> handlerStreams)
        {
            if (attributeSyntax.ArgumentList.Arguments.Count == 1)
            {
                var defaultValueExpression = attributeSyntax.ArgumentList.Arguments.First().Expression;
                var compilation = Compilation.Create("DefaultValueAttributeParameterValueCompilation",
                                                     syntaxTrees: new[] {defaultValueExpression.SyntaxTree});
                var semanticModel = compilation.GetSemanticModel(defaultValueExpression.SyntaxTree);
                var value = semanticModel.GetConstantValue(defaultValueExpression);

                if (value.HasValue)
                {
                    context.WeavedCodeContext
                        .CurrentCodeMemberPropertyDeclaration
                        .CurrentCodeMemberFieldDeclaration
                        .InitExpression = new CodePrimitiveExpression(value.Value);
                }
            }
        }
    }
}